# -*- coding: utf-8 -*-
"""
-------------------------------------------------
File Name: alarm
Description: This module defines the Alarm class, which represents an alarm object with various attributes and methods for handling alarms.
Author: 'li'
Date: 1/15/2024
-------------------------------------------------
Change Activity:
1/15/2024:
-------------------------------------------------
"""
from types import NoneType
from typing import Optional

import ll


class Alarm:
    """
    A class to represent an alarm.

    Attributes:
        timestamp (int): The timestamp of the alarm.
        ip (str): The IP address associated with the alarm.
        hostname (str): The hostname associated with the alarm.
        severity (str): The severity level of the alarm.
        alarm_type (str): The type of the alarm ('alarm' or 'recovery').
        alarm_info (str): Information about the alarm.
        note (str): Additional notes about the alarm.
        recovery (bool): Indicates if the alarm is a recovery.
        recovery_time (int): The time of recovery.
        manager_ip (str): The IP address of the manager.
        manager_port (int): The port of the manager.
        alarm_source (str): The source of the alarm.
        alarm_id (str): The unique ID of the alarm.
        last_send_time (datetime): The last time the alarm was sent.
        latest_monitoring_time (datetime): The latest monitoring time.
    """

    def __init__(
            self,
            timestamp=None,
            ip=None,
            hostname=None,
            severity=None,
            alarm_type=None,  # 'alarm,recovery'
            alarm_info=None,
            note: Optional[int] = None,
            recovery=False,
            recovery_time: Optional[int] = None,
            manager_ip=None,
            manager_port=None,
            alarm_source=None
    ):
        """
        Constructs all the necessary attributes for the Alarm object.

        Args:
            timestamp (int): The timestamp of the alarm.
            ip (str): The IP address associated with the alarm.
            hostname (str): The hostname associated with the alarm.
            severity (str): The severity level of the alarm.
            alarm_type (str): The type of the alarm ('alarm' or 'recovery').
            alarm_info (str): Information about the alarm.
            note (str): Additional notes about the alarm.
            recovery (bool): Indicates if the alarm is a recovery.
            recovery_time (int): The time of recovery.
            manager_ip (str): The IP address of the manager.
            manager_port (int): The port of the manager.
            alarm_source (str): The source of the alarm.
        """
        assert alarm_type in [None, 'alarm', 'recovery']
        assert severity in [None, "remind", "warning", "fatal"]  # p4 p3 p2
        self.timestamp = timestamp
        if timestamp is not None:
            self.occur_time = ll.TimeUtil.date_stamp_to_datetime(
                timestamp,
                format_str="%Y-%m-%d %H:%M:%S"
            )
        else:
            self.occur_time = ll.TimeUtil.date_stamp_to_datetime(
                ll.TimeUtil.get_current_timestamp(),
                format_str="%Y-%m-%d %H:%M:%S"
            )
        self.ip = ip
        self.alarm_capture_time = ll.TimeUtil.date_stamp_to_datetime(
            ll.TimeUtil.get_current_timestamp(),
            format_str="%Y-%m-%d %H:%M:%S"
        )
        self.hostname = hostname
        self.severity = severity
        self.alarm_type = alarm_type
        self.alarm_info = alarm_info
        self.note = note
        self.alarm_send = False
        self.recovery = recovery
        self.recovery_send = False
        self.recovery_time = recovery_time
        self.manager_ip = manager_ip  # for zabbix container.
        self.manager_port = manager_port  # for zabbix container.
        self.alarm_source = alarm_source
        self.last_send_time = None
        self.latest_monitoring_time = None
        self.alarm_id = self._get_alarm_id()

    def set_latest_monitoring_time(self, latest_monitoring_time):
        """
        Sets the latest monitoring time.

        Args:
            latest_monitoring_time (datetime): The latest monitoring time.
        """
        self.latest_monitoring_time = latest_monitoring_time

    def to_json(self):
        """
        Converts the Alarm object to a JSON serializable dictionary.

        Returns:
            dict: A dictionary representation of the Alarm object.
        """
        ret_json = {}
        attrs = dir(self)
        for attr in attrs:
            if str(attr).startswith('__'):
                continue
            v = getattr(self, attr)
            if isinstance(v, (str, int, float, bool, NoneType)):
                ret_json[attr] = v
        self.occur_time = ll.TimeUtil.date_stamp_to_datetime(
            self.timestamp,
            format_str="%Y-%m-%d %H:%M:%S"
        )
        return ret_json

    @staticmethod
    def json_to_obj(json_obj):
        """
        Converts a JSON serializable dictionary to an Alarm object.

        Args:
            json_obj (dict): A dictionary representation of an Alarm object.

        Returns:
            Alarm: An Alarm object.
        """
        alarm = Alarm()
        for k, v in json_obj.items():
            if str(k).startswith('__'):
                continue
            setattr(alarm, k, v)
        alarm.alarm_id = alarm._get_alarm_id()
        return alarm

    def _get_alarm_id(self):
        """
        Generates a unique ID for the alarm based on its attributes.

        Returns:
            str: The unique ID of the alarm.
        """
        content = f"{self.alarm_source}/{self.hostname}/{self.ip}/{self.manager_ip}/{self.manager_port}/{self.alarm_info}/{self.alarm_type}"
        return content
